headLen=10;
transitionLen=10;
pourerLen=10;
funnelDia=30;
pourerDia=8;
wallThickness=2;

funnel( funnelDia, headLen, transitionLen, pourerDia, pourerLen, wallThickness );

///////////////////////////////////////////////////////////////////////
module funnel( funnelDia, headLen, transitionLen, pourerDia, pourerLen, wallThickness )
{
    funnelRad=funnelDia/2.0;
    
rotate_extrude(convexity = 10)
    rotate([0,0,-90])
        difference()
        {
            difference()
            {
                pourerShape( funnelDia, headLen, transitionLen, pourerDia, pourerLen );
                translate([2*wallThickness,0,0]) offset(r=-wallThickness) pourerShape( funnelDia, headLen+2*wallThickness, transitionLen, pourerDia, pourerLen+2*wallThickness );
            }
            translate([-(headLen+transitionLen+pourerLen+1), -(funnelRad+1), 0]) square([headLen+transitionLen+pourerLen+1, funnelRad+1]);
        }
}
////////////////////////////////////////////////////////////////////////
module pourerShape( funnelDia, headLen, transitionLen, pourerDia, pourerLen )
{
    funnelRad=funnelDia/2.0;
    pourerRad=pourerDia/2.0;

    union()
    {
        hull()
        {    
            halfCircle(funnelRad);
            translate([-headLen,0,0]) halfCircle(funnelRad);
        }

        hull()
        {
            translate([-headLen,0,0]) halfCircle(funnelRad);
            translate([-headLen-transitionLen+pourerRad,0,0]) halfCircle(pourerRad);
        }

        hull()
        {
            translate([-headLen-transitionLen+pourerRad,0,0]) halfCircle(pourerRad);
            translate([-headLen-transitionLen-pourerLen/2,0,0]) square([pourerLen,pourerDia],true);
        }
    }
}
////////////////////////////////////////////////////////////////////////
module pourerShape3D( funnelDia, headLen, transitionLen, pourerDia, pourerLen )
{
    funnelRad=funnelDia/2.0;
    pourerRad=pourerDia/2.0;
    union()
    {
        hull()
        {
            halfSphere(funnelRad);
            translate([-headLen,0,0]) halfSphere(funnelRad);
        }

        hull()
        {
            translate([-headLen,0,0]) halfSphere(funnelRad);
            translate([-headLen-transitionLen+pourerRad,0,0]) halfSphere(pourerRad);
        }

        hull()
        {
            translate([-headLen-transitionLen+pourerRad,0,0]) halfSphere(pourerRad);
            translate([-headLen-transitionLen-pourerLen/2,0,0]) rotate([0,90,0]) cylinder(pourerLen,pourerRad, pourerRad, true, $fn=32);
        }
    }
}
////////////////////////////////////////////////////////////////////////
module halfCircle( radius )
{
    sidelen= 2*radius+1;
    difference()
    {
        circle( r = radius );
        translate([sidelen/2,0,0]) square(sidelen, true);
    }
}
////////////////////////////////////////////////////////////////////////
module halfSphere( radius )
{
    sidelen= 2*radius+1;
    difference()
    {
        sphere( r = radius );
        translate([sidelen/2,0,0]) cube(sidelen, true);
    }
}
